//This is the StatsLogon GUI object that represents a viewable panel representing logon controls

//import only what we need to speed things up
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Graphics;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

public class StatsLogon extends JPanel implements ActionListener {
	
	//declare class instance vars
	private Image background;
	private Image scaledbg;
	private Dimension prevsize;
	private JButton login_btn;
	private JButton clear_btn;
	private JButton newacc_btn;
	private JButton goback_btn;
	private JTextField username_fld;
	private JPasswordField password_fld;
	private JLabel instruct_lbl;
	private JLabel player_lbl;
	//common colors
	public static Color bgnorm = new Color(188, 143, 70);
	public static Color fgnorm = new Color(56, 5, 3);
	public static Color bgalt1 = new Color(221, 173, 98);
	public static Color fgalt1 = new Color(93, 15, 2);
	public static Color fgalt2 = new Color(242, 79, 1);
	
	//our constructor
	public StatsLogon() {
		
		//call our ancestor
		super();
		
		//build our layout with GridBag
		//assuming an invisible grid of 12 x 12
		
		this.setLayout(new GridBagLayout());
		//add a filler panel to fill the entire first 2 columns (1st-12th row) (1st-2nd column)
		JPanel temppan1 = new JPanel();
		temppan1.setOpaque(false);
		temppan1.setVisible(true);
		this.add(temppan1, new GridBagConstraints( 0, 0, 2, 8, 1, 1, 
			GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),
			0, 0));
		//add our instruction label
		//we want this to be at the top along the middle (1st row) (3rd-11th column)
		this.instruct_lbl = new JLabel("Instructions");
		this.instruct_lbl.setBackground(StatsLogon.bgnorm);
		this.instruct_lbl.setForeground(StatsLogon.fgnorm);
		this.instruct_lbl.setOpaque(true);
		this.add(this.instruct_lbl, new GridBagConstraints( 2, 0, 8, 1, 1, 1, 
			GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(3,0,3,0),
			0, 0));
		//add a filler panel to fill the lower 3rd column (2nd-9th row)
		JPanel temppan2 = new JPanel();
		temppan2.setOpaque(false);
		temppan2.setVisible(true);
		this.add(temppan2, new GridBagConstraints( 2, 1, 1, 7, 1, 1, 
			GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),
			0, 0));
		//add a filler panel to fill the right side (2nd-4th row) (4th-12th column)
		JPanel temppan3 = new JPanel();
		temppan3.setOpaque(false);
		this.add(temppan3, new GridBagConstraints( 3, 1, 9, 3, 1, 1, 
			GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, new Insets(0,0,0,0),
			0, 0));
		//add our player label
		//we want this to be at the center below the text of the background (5th row) along the middle (6th column)
		this.player_lbl = new JLabel("Player");
		this.player_lbl.setBackground(StatsLogon.bgnorm);
		this.player_lbl.setForeground(StatsLogon.fgnorm);
		this.player_lbl.setOpaque(true);
		this.add(this.player_lbl, new GridBagConstraints( 5, 4, 2, 1, 1, 0.2, 
			GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0),
			0, 0));
		//add our username label
		//we want this to be at the center below the text of the background (6th row) along the middle (5th column)
		JLabel username_lbl = new JLabel("username:");
		username_lbl.setBackground(StatsLogon.bgnorm);
		username_lbl.setForeground(StatsLogon.fgnorm);
		username_lbl.setOpaque(true);
		this.add(username_lbl, new GridBagConstraints( 4, 5, 1, 1, 1, 0.2, 
			GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0,0,0,0),
			0, 0));
		//add our password label
		//we want this to be at the center below the text of the background (7th row) along the middle (5th column)
		JLabel password_lbl = new JLabel("password:");
		password_lbl.setBackground(StatsLogon.bgnorm);
		password_lbl.setForeground(StatsLogon.fgnorm);
		password_lbl.setOpaque(true);
		this.add(password_lbl, new GridBagConstraints( 4, 6, 1, 1, 1, 0.2, 
			GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0,0,0,0),
			0, 0));
		//add our username field
		//we want this to be at the center below the text of the background (6th row) along the middle (6th-8th column)
		this.username_fld = new JTextField(15);
		//this.username_fld.setBackground(StatsLogon.bgnorm);
		//username_fld.setForeground(StatsLogon.fgnorm);
		//add action listener to handler ENTER key presses as login attempts
		this.username_fld.addActionListener(this);
		this.add(this.username_fld, new GridBagConstraints( 5, 5, 3, 1, 1, 0.2, 
			GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),
			0, 0));
		//add our password field
		//we want this to be at the center below the text of the background (7th row) along the middle (6th-8th column)
		this.password_fld = new JPasswordField(15);
		//this.password_fld.setBackground(StatsLogon.bgnorm);
		//password_fld.setForeground(StatsLogon.fgnorm);
		//add action listener to handler ENTER key presses as login attempts
		this.password_fld.addActionListener(this);
		this.add(this.password_fld, new GridBagConstraints( 5, 6, 3, 1, 1, 0.2, 
			GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),
			0, 0));
		//add our login button
		//we want this to be on the left under the entry fields (8th row) (5th-6th column)
		this.login_btn = new JButton("Login");
		this.login_btn.setBackground(StatsLogon.bgnorm);
		this.login_btn.setForeground(StatsLogon.fgnorm);
		this.login_btn.addActionListener(this);
		/*
		//give this button a special input mapping
		// to fire when the ENTER key is pressed while the window is in focus
			this.login_btn.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW).put(
				KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), new Object());
		*/
		//scratch that
		this.add(this.login_btn, new GridBagConstraints( 4, 7, 2, 1, 1, 0.3, 
			GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),
			0, 0));
		//add our clear button
		//we want this to be on the right under the entry fields (8th row) (7th-8th column)
		this.clear_btn = new JButton("Clear");
		this.clear_btn.setBackground(StatsLogon.bgnorm);
		this.clear_btn.setForeground(StatsLogon.fgnorm);
		this.clear_btn.addActionListener(this);
		this.add(this.clear_btn, new GridBagConstraints( 6, 7, 2, 1, 1, 0.3, 
			GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),
			0, 0));
		//add our new-account button
		//we want this to be on the far right under the entry fields (8th row) (9th-10th column)
		this.newacc_btn = new JButton("New Account");
		this.newacc_btn.setBackground(StatsLogon.bgnorm);
		this.newacc_btn.setForeground(StatsLogon.fgnorm);
		this.newacc_btn.addActionListener(this);
		//this.newacc_btn.setEnabled(false);
		this.add(this.newacc_btn, new GridBagConstraints( 8, 7, 2, 1, 1, 0.3, 
			GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),
			0, 0));
		//add a filler panel to fill the leftover (9th-11th row) (4th-12th column)
		JPanel temppan4 = new JPanel();
		temppan4.setOpaque(false);
		this.add(temppan4, new GridBagConstraints( 3, 8, 9, 2, 1, 1, 
			GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0,0,0,0),
			0, 0));
		//add our go back button
		//we want this to be at the bottom right corner (12th row) (11th column)
		this.goback_btn = new JButton("Go Back");
		this.goback_btn.setBackground(StatsLogon.bgnorm);
		this.goback_btn.setForeground(StatsLogon.fgnorm);
		this.goback_btn.addActionListener(this);
		this.add(this.goback_btn, new GridBagConstraints( 10, 11, 2, 1, 1, 0.3, 
			GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0),
			0, 0));
		
		//set a reasonable size to match the ratio of our splash image
		this.setPreferredSize(new Dimension(500, 375));
		
		//try to get our splash image
		//if we cannot retrieve the image, it is somewhat serious
		//but I don't know what we could do from that point on :(
		try{
			background = ImageIO.read(new File("images\\SplashMedium.jpg"));
		}catch (IOException EXC){
			//this likely means there was some problem accessing the image file
		}catch (IllegalArgumentException EXC){
			//this likely means that for some reason we couldn't create the File object
		}
		
		//setup our text etc
		this.setupPlayerLogon();
		
		//setup visibilities
		this.setVisible(true);
		this.setOpaque(true);
		
	}
	
	//override this so that we can customize drawing of the component
	//specifically so that we always have our pretty splash screen behind us :D
	public void paintComponent(Graphics g) {
		
		//call our ancestor
		super.paintComponent(g);
		
		System.out.println("$1GameLogon: painting...");
		
		//getSize is a retarded method, as such it requires
		//  we pass a Dimension object that it will use by referrence to store the size
		//the retarded part is that it also returns the same Dimension object
		//  go figure...
		Dimension panelsize = new Dimension(0,0);
		this.getSize(panelsize);
		
		//check if previous size has been declared yet
		if (this.prevsize == null){
			this.prevsize = new Dimension(panelsize);
		}
		
		//check if we need to rescale the image
		// this can occur if the component size changed
		// or it can occur if the image has not been scaled yet
		if (this.scaledbg == null || !panelsize.equals(this.prevsize)){
			this.scaledbg = background.getScaledInstance(panelsize.width,
			panelsize.height, Image.SCALE_SMOOTH);
		}
		g.drawImage(scaledbg, 0, 0, null);
		
		//reset the previous scale size
		this.prevsize = new Dimension(panelsize);
		
	}
	
	//convenience method for setting up parameters for player logon
	public void setupPlayerLogon() {
		
		instruct_lbl.setText("Player, login or create a new account to access your account statistics.");
		player_lbl.setText("Stats Logon");
		//draw what we have changed
		this.repaint();
		
	}
	
	//hidden convenience method for showing the user an information notice
	private void showInfoNotice(String info, String title) {
		
		this.repaint();
		JOptionPane.showMessageDialog(this, info, title, JOptionPane.INFORMATION_MESSAGE);
		
	}
	
	//hidden convenience method for clearing out user name and password info
	private void clearFields() {
		
		this.username_fld.setText("");
		this.password_fld.setText("");
		
	}
	
	//hidden convenience method for attempting to log in
	private void loginPlayer() {
		
		//declare some vars
		String curruser = this.username_fld.getText();
		String currpass = new String(this.password_fld.getPassword());
		boolean result = false;
		
		result = UIController.authenticateUser(curruser, currpass);
		//result = ((curruser.equals("admin")) && (currpass.equals("admin")));
		if (!result){
			this.showInfoNotice("The account could not be authenticated!"
				+ "\nThe password is incorrect or the account does not exist."
				+ "\n\nMake sure CAPSLOCK is off."
				+ "\nClick the \"New Account\" button to create an account.", "Authentication Failure");
		}else{
			UIController.printPopup("Player has been authenticated!", 7.5);
			this.clearFields();
			//prepare stats view
			((StatsView)UIController.grabState("StatsView")).getPlayers();
			((StatsView)UIController.grabState("StatsView")).setPlayer(curruser);
			UIController.changeState("StatsView");
		}
		
	}
	
	//hidden convenience method for attempting to create a new account
	private void createPlayer() {
		
		//declare some vars
		String curruser = this.username_fld.getText();
		String currpass = new String(this.password_fld.getPassword());
		boolean result = false;
		
		result = UIController.createUser(curruser, currpass);
		if (!result){
			this.showInfoNotice("The account could not be created!"
				+ "\nThe username already exists or the username/password are not in the correct format."
				+ "\n\nThe password must be from 6 to 16 characters long."
				+ "\nThe username must be from 4 to 32 characters long."
				+ "\nThe password and username must be a valid String.", "Creation Failure");
		}else{
			this.loginPlayer();
		}
		
	}
	
	//implement ActionListener
	public void actionPerformed(ActionEvent EVE) {
		
		//determine the caller
		Object tmpobj = EVE.getSource();
		if (tmpobj.equals(this.username_fld)){
			//check if ENTER key sent
			//System.out.println(EVE.getID());
			//login procedures
			this.loginPlayer();
		}else if (tmpobj.equals(this.password_fld)){
			//check if ENTER key sent
			//System.out.println(EVE.getID());
			//login procedures
			this.loginPlayer();
		}else if (tmpobj.equals(this.goback_btn)){
			UIController.changeState("MainView");
		}else if (tmpobj.equals(this.clear_btn)){
			this.clearFields();
		}else if (tmpobj.equals(this.login_btn)){
			//login procedures
			this.loginPlayer();
		}else if (tmpobj.equals(this.newacc_btn)){
			//creation procedures
			this.createPlayer();
		}
		
	}
	
}